﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Runtime.Serialization;
using JXT.PrimaryKey.Batman.Core.WcfService;

namespace JXT.PrimaryKey.Batman.WcfService.Client.Wrapper
{
    internal abstract class WrapperServiceBase
    {
        private IClientChannel _innerClientChannel;

        private string _authenticationId;

        private string _authenticationKey;

        public WrapperServiceBase(IClientChannel innerClientChannel, string authenticationId, string authenticationKey)
        {
            _innerClientChannel = innerClientChannel;
            _authenticationId = authenticationId;
            _authenticationKey = authenticationKey;
        }

        /// <summary>
        /// 封装Action调用,将服务器异常转化为WcfOperationException
        /// </summary>
        /// <param name="action"></param>
        protected void WrapperAction(Action action, bool isSendAuthentication = false)
        {
            try
            {
                if (isSendAuthentication)
                {
                    if (_innerClientChannel == null)
                        throw new ArgumentException("_innerClientChannel is null!");
                    using (OperationContextScope scope = new OperationContextScope(_innerClientChannel))
                    {
                        WebOperationContext.Current.OutgoingRequest.Headers.Add(ServiceEnvironment.AuthenticationIdHeader, _authenticationId);
                        WebOperationContext.Current.OutgoingRequest.Headers.Add(ServiceEnvironment.AuthenticationKeyHeader, _authenticationKey);
                        action();
                    }
                }
                else
                {
                    action();
                }
            }
            catch (ProtocolException e)
            {
                var webException = e.InnerException as WebException;
                WebHttpError error;
                string rawString = String.Empty;
                try
                {
                    DataContractSerializer ds = new DataContractSerializer(typeof(WebHttpError));
                    var fs = webException.Response.GetResponseStream();
                    System.IO.StreamReader sr = new System.IO.StreamReader(fs);
                    rawString = sr.ReadToEnd();
                    fs.Seek(0, System.IO.SeekOrigin.Begin);
                    error = ds.ReadObject(fs) as WebHttpError;
                    fs.Dispose();
                }
                catch (Exception ex)
                {
                    error = new WebHttpError()
                    {
                        Code = (int)WebHttpErrorCode.Unknown,
                        Message = ex.Message,
                        Status = 400
                    };
                }
                throw new WcfOperationException(e, error, rawString);
            }
            catch (Exception e)
            {
                throw new WcfOperationException(e, new WebHttpError()
                {
                    Code = (int)WebHttpErrorCode.Unknown,
                    Message = e.Message,
                    Status = 200
                }, String.Empty);
            }
        }

        /// <summary>
        /// 封装Func`T,将服务器异常转化为WcfOperationException
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="fun"></param>
        /// <returns></returns>
        protected T WrapperFunction<T>(Func<T> fun, bool isSendAuthentication = false)
        {
            try
            {
                //return fun();
                if (isSendAuthentication)
                {
                    if (_innerClientChannel == null)
                        throw new ArgumentException("_innerClientChannel is null!");
                    using (OperationContextScope scope = new OperationContextScope(_innerClientChannel))
                    {
                        WebOperationContext.Current.OutgoingRequest.Headers.Add(ServiceEnvironment.AuthenticationIdHeader, _authenticationId);
                        WebOperationContext.Current.OutgoingRequest.Headers.Add(ServiceEnvironment.AuthenticationKeyHeader, _authenticationKey);
                        return fun();
                    }
                }
                else
                {
                    return fun();
                }
            }
            catch (ProtocolException e)
            {
                var webException = e.InnerException as WebException;
                WebHttpError error;
                string rawString = String.Empty;
                try
                {
                    DataContractSerializer ds = new DataContractSerializer(typeof(WebHttpError));
                    var fs = webException.Response.GetResponseStream();
                    System.IO.StreamReader sr = new System.IO.StreamReader(fs);
                    rawString = sr.ReadToEnd();
                    fs.Seek(0, System.IO.SeekOrigin.Begin);
                    error = ds.ReadObject(fs) as WebHttpError;
                    fs.Dispose();
                }
                catch (Exception ex)
                {
                    error = new WebHttpError()
                    {
                        Code = (int)WebHttpErrorCode.Unknown,
                        Message = ex.Message,
                        Status = 400
                    };
                }
                throw new WcfOperationException(e, error, rawString);
            }
            catch (Exception e)
            {
                throw new WcfOperationException(e, new WebHttpError()
                {
                    Code = (int)WebHttpErrorCode.Unknown,
                    Message = e.Message,
                    Status = 200
                }, String.Empty);
            }
        }
    }
}
